home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
c
/
gymake12.zip
/
MAKE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-18
|
19KB
|
861 lines
/*
* make.c An imitation of the Unix MAKE facility
*
* 88-10-01 v1.0 created by greg yachuk, placed in the public domain
* 88-10-06 v1.1 changed prerequisite list handling
* 88-11-11 v1.2 fixed some bugs and added environment variables
*
*/
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#ifdef MSDOS
#include <stdlib.h>
#include <process.h>
#include <dos.h>
#else
#include <sys/errno.h>
#include <sys/wait.h>
#endif
#include "make.h"
#include "tstring.h"
#include "decl.h"
#ifdef MSDOS
#define PATH_SEPARATOR ";"
#define FILE_SEPARATOR "/\\"
#else
#define PATH_SEPARATOR ":"
#define FILE_SEPARATOR "/"
#endif
#define MAKEINI "default.mk"
char *shell_cmds[] = {
#ifdef MSDOS
"dir", "type", "rem", "pause", "date", "time", "ren", "rename",
"ver", "vol", "break", "verify", "mkdir", "md", "exit", "ctty",
"echo", "if", "cls", "chdir", "cd", "rmdir", "rd", "copy", "del",
"erase",
#endif
NULL,
};
targptr target_list = NULL; /* list of target nodes */
fileptr file_list = NULL; /* list of file nodes */
symptr symbol_list = NULL; /* list of symbol nodes */
shellptr shell_list = NULL; /* list of shell nodes */
int make_level = 0; /* for counting new_make()'s */
targptr first_targ = NULL; /* first target, in case nothing explicit */
targptr suffix_targ = NULL; /* .SUFFIXES target pointer */
char **tlist = NULL; /* command line targets */
char **flist = NULL; /* command line make files */
char **mlist = NULL; /* command line macros */
int tmax = 0; /* max size of tlist */
int fmax = 0; /* max size of flist */
int mmax = 0; /* max size of mlist */
int depend = 0; /* -d option */
int display = 0; /* -D option */
int envirn = 0; /* -e option */
int ignore = 0; /* -i option */
int noexec = 0; /* -n option */
int readdef = 1; /* -r option */
int silent = 0; /* -s option */
int touch = 0; /* -t option */
int dispcount = 0; /* used for -D option */
long now; /* time at startup */
char *makeflags; /* value to update the MAKEFLAGS macro with */
main(argc, argv)
int argc;
char **argv;
{
REGISTER int i;
REGISTER targptr targp;
symptr symp;
char *envp;
char **envv;
/* initialize the various global lists */
depend = 0;
dispcount = 0;
target_list = NULL;
file_list = NULL;
shell_list = NULL;
/* allocate space for command line targets, files and macros */
tlist = grow_list(NULL, &tmax);
flist = grow_list(NULL, &fmax);
mlist = grow_list(NULL, &mmax);
/* process MAKEFLAGS environment variable, first */
symp = get_symbol("MAKEFLAGS", 0);
if (symp->svalue != NULL)
{
/* chop up the MAKEFLAGS and feed them to to make_args() */
envp = tstrcpy(symp->svalue);
envv = tokenize(envp);
for (i=0; envv[i] != NULL; i++);
make_args(i, envv);
/* free the vector of pointers, and the string itself, */
/* since you cannot have macros, targets or makefiles */
/* in the MAKEFLAGS macro. */
tfree(envv);
tfree(envp);
tfree(makeflags); /* ignore this, since we just read it */
}
make_args(--argc, ++argv); /* process command line options */
add_macro(makeflags, 0); /* update the MAKEFLAGS macro */
tfree(makeflags);
/* add command line macros, so they DON'T get overridden */
for(i = 0; mlist[i] != NULL; i++)
add_macro(mlist[i], 1);
tfree(mlist); /* all done with macros */
if (noexec)
silent = touch = 0; /* -n always displays; never touches */
if (dispcount > 1)
display = 1; /* display `default.mk' on -DD */
first_targ = NULL; /* used in parse() */
if (readdef)
parse(fopenp(MAKEINI, "r")); /* read in `default.mk' */
if (dispcount > 0)
display = 1; /* display makefile's on -D */
first_targ = NULL; /* get first target in `makefile' */
/* parse the makefiles given on command line */
for(i = 0; flist[i] != NULL; i++)
{
parse(equal(flist[i],"-") ? fdopen(dup(fileno(stdin)), "r")
: fopen(flist[i], "r"));
}
/* no makefiles specified, so use "makefile" */
if (i == 0)
parse(fopen("makefile", "r"));
tfree(flist); /* all done with makefile's */
if ((targp = get_target(".INIT")) != NULL)
build(targp->tshell); /* process the .INIT rule */
for (i = 0; tlist[i] != NULL; i++)
make(tlist[i], 1); /* process command line targets */
tfree(tlist); /* all done with targets */
/* if no targets specified, make the first one */
if (i == 0 && first_targ)
make(first_targ->tfile->fname, 1);
if ((targp = get_target(".DONE")) != NULL)
build(targp->tshell); /* process the .DONE rule */
return (0); /* not exit(); see new_make() */
}
/*
* make_args - process the command line arguments
*/
make_args(argc, argv)
int argc;
char **argv;
{
REGISTER int tlen;
REGISTER int flen;
REGISTER int mlen;
char *tmf;
now = time(NULL); /* get current date & time */
makeflags = tstrcpy("MAKEFLAGS+=");
tlen = flen = mlen = 0;
for (;argc != 0; ++argv, --argc)
{
if (**argv != '-')
{
/* doesn't start with '-'; must be macro or target */
if (strchr(*argv, '='))
{ /* store as a macro */
if (mlen == mmax)
mlist = grow_list(mlist, &mmax);
mlist[mlen++] = *argv;
}
else
{ /* store as a target */
if (tlen == tmax)
tlist = grow_list(tlist, &tmax);
tlist[tlen++] = *argv;
}
continue;
}
/* must be an option */
tmf = tstrcat(makeflags, *argv);
tfree(makeflags);
makeflags = tstrcat(tmf, " ");
tfree(tmf);
while (*argv && *++*argv)
{
switch (**argv)
{
case 'd': /* show dependencies */
depend++;
break;
case 'D': /* display makefiles */
dispcount++;
break;
case 'e': /* don't override environment */
envirn = 1;
break;
case 'f': /* new makefile name */
if (argc < 2)
usage();
if (flen == fmax)
flist = grow_list(flist, &fmax);
++argv, --argc;
flist[flen++] = *argv;
/* save, but ignore, the makefile */
tmf = tstrcat(makeflags, *argv);
tfree(makeflags);
makeflags = tstrcat(tmf, " ");
tfree(tmf);
*argv = NULL;
break;
case 'i': /* ignore errors */
ignore = 1;
break;
case 'n': /* don't execute commands */
noexec = 1;
break;
case 'r': /* don't read default.mk */
readdef = 0;
break;
case 's': /* don't echo commands */
silent = 1;
break;
case 't': /* touch files, don't build */
touch = 1;
break;
default:
usage(); /* never returns */
}
}
}
/* terminate all lists with a NULL pointer */
tlist[tlen] = NULL;
flist[flen] = NULL;
mlist[mlen] = NULL;
/* let the caller update the makeflags macro */
}
/*
* grow_list - expand the list of pointers by a factor of two
*/
char **
grow_list(list, len)
char **list;
int *len;
{
REGISTER int l;
l = *len; /* get current length */
/* if list is NULL, start off with a default list */
if (list == NULL)
list = (char **) talloc(((l=1)+1) * sizeof(char *));
else
list = (char **) trealloc((char *)list,
((l <<=1)+1)*sizeof(char *));
if (list == NULL)
terror(1, "too many options");
/* if we are initially allocating it, set first pointer to NULL */
if (l == 1)
*list = NULL;
*len = l; /* update current length */
return (list);
}
/*
* fopenp - open file in current directory or along PATH
*/
FILE *
fopenp(fname, type)
char *fname;
char *type;
{
REGISTER int len;
REGISTER char *fpath;
FILE *fd;
char *path;
char *tp;
/* try to open file relative to current directory */
if ((fd = fopen(fname, type)) != NULL)
return (fd);
/* didn't work, search along path */
if ((path = getenv("PATH")) == NULL)
return (NULL);
path = tstrcpy(path); /* allocate string and copy */
fpath = talloc(strlen(path) + strlen(fname) + 2);
/